package cn.dansj.service.Impl;

import cn.dansj.repository.ConnectionRepository;
import cn.dansj.service.ConnectionService;
import cn.dansj.common.utils.transfer.GetTime;
import cn.dansj.common.utils.transfer.Transformation;
import cn.dansj.common.utils.transfer.Verification;
import com.xxl.job.entity.Connection;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;

@Service
public class ConnectionServiceImpl implements ConnectionService {
    private final ConnectionRepository connectionRepository;

    @PersistenceContext
    private EntityManager entityManager;

    public ConnectionServiceImpl(ConnectionRepository connectionRepository) {
        this.connectionRepository = connectionRepository;
    }

    //页面查询
    public Page<Connection> search(Integer pageNum,
                                   Integer pageLimit,
                                   String name,
                                   String connection_info,
                                   String status) {
        Sort sort = Sort.by(Sort.Direction.DESC, "crtTime");
        Pageable pageable = PageRequest.of(pageNum - 1, pageLimit, sort);
        Specification<Connection> specification = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicateList = new ArrayList<>();
            if (Verification.checkNotNull(name)) {
                Expression<String> nameExpr = criteriaBuilder.lower(root.get("name"));
                predicateList.add(criteriaBuilder.like(nameExpr, Transformation.sqlLikeToLowCase(name)));
            }
            if (Verification.checkNotNull(connection_info)) {
                Expression<String> connectExpr = criteriaBuilder.lower(root.get("connectionInfo"));
                predicateList.add(criteriaBuilder.like(connectExpr, Transformation.sqlLikeToLowCase(connection_info)));
            }
            if (Verification.checkNotNull(status)) {
                predicateList.add(criteriaBuilder.equal(root.get("status"), status));
            }

            Predicate[] predicates = new Predicate[predicateList.size()];
            return criteriaBuilder.and(predicateList.toArray(predicates));
        };
        return connectionRepository.findAll(specification, pageable);
    }

    public Connection getConnectionBySequence(String sequence) {
        return connectionRepository.getConnectionBySequence(sequence);
    }

    public List<Connection> getConnectionByDbType(String dbType) {
        return connectionRepository.getConnectionByDbType(dbType);
    }

    //更新连接状态和监控状态
    @Transactional
    public void updateConnectionStatus(String sequence, String monitor, String status) {
        if (Verification.checkNotNull(sequence) && (Verification.checkNotNull(monitor) || Verification.checkNotNull(status))) {
            CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
            CriteriaUpdate<Connection> update = criteriaBuilder.createCriteriaUpdate(Connection.class);
            Root<Connection> root = update.from(Connection.class);

            Predicate seqExpr = criteriaBuilder.equal(root.get("sequence"), sequence);

            if (Verification.checkNotNull(monitor)) {
                update.set(root.get("monitor"), Integer.valueOf(monitor));
            }
            if (Verification.checkNotNull(status)) {
                update.set(root.get("status"), Integer.valueOf(status));
            }

            update.set(root.get("update_time"), GetTime.dbTimestamp()).where(seqExpr);

            entityManager.createQuery(update).executeUpdate();
        }

    }

    //校验监控状态
    public int getMonitor(String sequence) {
        return connectionRepository.getMonitor(sequence);
    }

    @Override
    public List<Connection> getMonitor() {
        return connectionRepository.getMonitor();
    }

    @Override
    public void save(Connection connection) {
        connectionRepository.save(connection);
    }

    @Override
    public void save(List<Connection> connections) {
        connectionRepository.saveAll(connections);
    }


    //获取所有连接信息
    public List<Connection> getAll() {
        return connectionRepository.findAll(Sort.by(Sort.Direction.DESC, "sequence"));
    }

    //通过名称获取连接信息
    public Connection getConnectionByName(String name) {
        return connectionRepository.getConnectionByName(name);
    }

    public List<Connection> getConnectionsByDbTypes(List<String> dbTypes) {
        return connectionRepository.getConnectionsByDbTypeIn(dbTypes);
    }

}
